package com.example.demo.config;

import com.example.demo.entity.PermissionEntity;
import com.example.demo.filter.JWTAuthorizationFilter;
import com.example.demo.filter.JWTLoginFilter;
import com.example.demo.mapper.PermissionMapper;
import com.example.demo.service.MemberUserDetailService;
import com.example.demo.util.MD5Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import java.util.List;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {


    @Autowired
    private MemberUserDetailService memberUserDetailService;


    @Autowired
    private PermissionMapper permissionMapper;

    @Autowired
    private PersistentTokenRepository persistentTokenRepository;

    /**
     * 添加授权账户
     *
     * 实际上就是将用户 账号、密码、和权限添加进SpringSecurity
     * */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

//        auth.inMemoryAuthentication().withUser("root").password("root")
//        .authorities("addMember","delMember","updateMember");
//        auth.inMemoryAuthentication().withUser("root1").password("root1").authorities("showMember");

        auth.userDetailsService(memberUserDetailService).passwordEncoder(new PasswordEncoder() {

            /**
             *
             * @author HuangGaoTao
             * @date 2021/04/13 23:06
             * @param rawPassword
             * @return java.lang.String
             */
            @Override
            public String encode(CharSequence rawPassword) {
                return MD5Util.encode((String) rawPassword);
            }

            /**
             * rawPassword 用户输入的密码
             * encodedPassword 数据库DB的密码
             * @param rawPassword
             * @param encodedPassword
             * @return
             */
            public boolean matches(CharSequence rawPassword, String encodedPassword) {
                //对用户输入的密码进行加密
                String rawPass = MD5Util.encode((String) rawPassword);
                //再和数据库密码进行比对
                boolean result = rawPass.equals(encodedPassword);
                return result;
            }
        });

    }



    //绑定权限
    @Override
    protected void configure(HttpSecurity http) throws Exception {


        //将所有权限遍历出来，并给
        List<PermissionEntity> allPermission = permissionMapper.findAllPermission();

        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry expressionInterceptUrlRegistry = http.authorizeRequests();

        //将所有请求对应的权限添加到SpringSecurity中
        allPermission.forEach((permission)->{
            expressionInterceptUrlRegistry.antMatchers(permission.getUrl())
                    .hasAnyAuthority(permission.getPermTag());
        });
        http
                .addFilter(new JWTAuthorizationFilter(authenticationManager()))
                .addFilter(new JWTLoginFilter(authenticationManager())).csrf().disable()
                //剔除session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        expressionInterceptUrlRegistry
                .antMatchers("/auth/login").permitAll()
                .antMatchers("/**").fullyAuthenticated();

        http.rememberMe()
                .rememberMeParameter("rememberMe")
                .tokenRepository(persistentTokenRepository)
                .userDetailsService(memberUserDetailService)
                .tokenValiditySeconds(60);

        http.logout().logoutSuccessUrl("/login");
    }

}
